package com.redispro.handler;

import com.redispro.entity.Shop;
import com.redispro.service.IShopService;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @Auther: 李 力
 * @Date: 2024/12/3
 * @Description: com.redispro.handler
 * @version: 1.0
 */
@Component
public class ShopImport implements CommandLineRunner {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private IShopService shopService;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public void run(String... args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(this::loadShopData);
    }

    @Transactional(rollbackFor = Exception.class)
    public void loadShopData() {
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("shop:upload");
        RLock rLock = readWriteLock.writeLock();
        try {
            rLock.lock();
            //1.查询店铺信息
            List<Shop> list = shopService.lambdaQuery().eq(Shop::getIsLoad, "0").list();
            if (list.isEmpty()) {
                return;
            }
            //2.根据店铺类型分组
            Map<Long, List<Shop>> map = list.stream().collect(Collectors.groupingBy(Shop::getTypeId));
            //3.分批写入redis
            for (Map.Entry<Long, List<Shop>> entry : map.entrySet()) {
                //id
                Long commonId = entry.getKey();
                //店铺信息
                List<Shop> shops = entry.getValue();
                //4.存入redis
                String key = "shop:geo:" + commonId;
                List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(shops.size());
                for (Shop shop : shops) {
//                redisTemplate.opsForGeo().add(key, new Point(shop.getX(), shop.getY()), shop.getId().toString());
                    locations.add(new RedisGeoCommands.GeoLocation<>(shop.getId().toString(), new Point(shop.getX(), shop.getY())));
                }
                redisTemplate.opsForGeo().add(key, locations);
            }
            list.forEach(shop -> shop.setIsLoad("1"));
            shopService.updateBatchById(list);
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            rLock.unlock();
        }
    }
}
